#include <bits/stdc++.h>

using std::cin;
using std::cout;
using std::endl;
using std::swap;
using std::vector;

struct edge {
	int v, u, cost;

	edge() {}
	edge(int v, int u, int cost) : v(v), u(u), cost(cost) {}
};

void input(int &n, vector <edge> &graph) {
	int m, k;
    cin >> n >> m >> k;
	for (int i = 0; i < m * 2; ++i) {
		int x, y, c;
		cin >> x >> y >> c;
		if (x >= y) {
			continue;
		}
		graph.push_back(edge(x, y, c));
	}
	for (int i = 1; i <= k; ++i) {
		graph.push_back(edge(0, i, 0));
	}
	return;
}

struct dsu {
	vector <int> ancestor, rank;

	dsu() {}
	dsu(int n) : ancestor(n + 1), rank(n + 1) {
		for (int i = 0; i <= n; ++i) {
			ancestor[i] = i;
		}
	}

	int get(int v) {
		if (ancestor[v] == v) {
			return v;
		}
		return ancestor[v] = get(ancestor[v]);
	}

	bool unite(int v, int u) {
		v = get(v);
		u = get(u);
		if (v == u) {
			return 0;
		}
		if (rank[v] < rank[u]) {
			swap(v, u);
		}
		ancestor[u] = v;
		if (rank[v] == rank[u]) {
			++rank[v];
		}
		return 1;
	}
};

void solve(int n, vector <edge> &a) {
	dsu DSU(n);
	sort(a.begin(), a.end(), [](edge e1, edge e2) {
		return e1.cost < e2.cost;
	});
	int answer = 0;
	for (auto e: a) {
		if (DSU.unite(e.v, e.u) && e.cost > 0) {
			answer += e.cost;
		}
	}
	cout << answer << endl;
	return;
}

int main() {
	int n;
	vector <edge> a;
	input(n, a);
	solve(n, a);
	return 0;
}
